#include <SDL.h>

#include "direction.h"
#include "ship.h"
#include "sprite.h"
#include "map.h"

extern Sprite* g_sprites;
extern Ship* g_select_ship;
extern int g_wind_direction;

const int g_center_ship_offset = 19;

int diff_move[DIR_MAX][DIR_MAX] = {
    {0, -1, -2, -3, -4, -3, -2, -1},   /* DIR_UP */
    {-1, 0, -1, -2, -3, -4, -3, -2},   /* DIR_UP_RIGHT */
    {-2, -1, 0, -1, -2, -3, -4, -3},   /* DIR_RIGHT */
    {-3, -2, -1, 0, -1, -2, -3, -4},   /* DIR_DOWN_RIGHT */
    {-4, -3, -2, -1, 0, -1, -2, -3},   /* DIR_DOWN */
    {-3, -4, -3, -2, -1, 0, -1, -2},   /* DIR_DOWN_LEFT */
    {-2, -3, -4, -3, -2, -1, 0, -1},   /* DIR_LEFT */
    {-1, -2, -3, -4, -3, -2, -1, 0}};  /* DIR_UP_LEFT */

void InitShip(Ship* ship, int x, int y) {
    ship->x = x;
    ship->y = y;
    ship->x_offset = g_center_ship_offset;
    ship->y_offset = g_center_ship_offset;
    ship->direction = DIR_LEFT;
    ship->status = EST_NONE;
}


void DrawShip(Ship* ship, int x, int y) {
    Sprite* sprite = g_sprites + ship->direction;

    int delta_x = ship->x_offset - g_center_ship_offset;
    int delta_y = ship->y_offset - g_center_ship_offset;

    x += delta_x + delta_y;
    y += delta_x / 2 - delta_y / 2;

    DrawSprite(sprite, x, y);

    if (ship->status == EST_SELECTED) {
        Sprite* sprite_select = g_sprites + DIR_MAX + ship->direction;
        DrawSprite(sprite_select, x, y);
    }
}

Ship* SelectShip(int x, int y) {
    Ship* ship = ShipOnMap(x, y);
    if (ship && ship != g_select_ship) {
        if (g_select_ship)
            g_select_ship->status = EST_NONE;
        ship->status = EST_SELECTED;
        g_select_ship = ship;
        return ship;
    }
    return 0;
}

int LenMove(int direction) {
    return 6 + diff_move[g_wind_direction][direction];
}

int CanMoveShip(Ship* ship, int x, int y) {
    int a = ship->x - x;
    int b = ship->y - y;
    if (!(ship->x == x && ship->y == y)) {
        if (a > 0  && a == -b && a < LenMove(DIR_UP))
            return 1 + DIR_UP;
        if (a == 0 && b < 0   && -b < LenMove(DIR_UP_RIGHT))
            return 1 + DIR_UP_RIGHT;
        if (a < 0  && a == b  && -a < LenMove(DIR_RIGHT))
            return 1 + DIR_RIGHT;
        if (b == 0 && a < 0   && -a < LenMove(DIR_DOWN_RIGHT))
            return 1 + DIR_DOWN_RIGHT;
        if (b > 0  && a == -b &&  b < LenMove(DIR_DOWN))
            return 1 + DIR_DOWN;
        if (a == 0 && b > 0   &&  b < LenMove(DIR_DOWN_LEFT))
            return 1 + DIR_DOWN_LEFT;
        if (a > 0  && a == b  &&  a < LenMove(DIR_LEFT))
            return 1 + DIR_LEFT;
        if (b == 0 && a > 0   &&  a < LenMove(DIR_UP_LEFT))
            return 1 + DIR_UP_LEFT;
    }
    return 0;
}

void NormShipDirection(Ship* ship) {
    ship->direction = NormDirection(ship->direction);
}

void NormShipOffset(Ship* ship) {
    int delta = g_center_ship_offset * 2;

    ship->x += ship->x_offset / delta;
    ship->y += ship->y_offset / delta;

    ship->x_offset %= delta;
    ship->y_offset %= delta;

    if (ship->x_offset < 0) {
        ship->x--;
        ship->x_offset += delta;
    }

    if (ship->y_offset < 0) {
        ship->y--;
        ship->y_offset += delta;
    }
}

int MinRotateDirectin(Ship* ship, int direction) {
    if (DeltaDirection(ship->direction, direction) < DeltaDirection(ship->direction, NormDirection(direction - 4))) {
        return direction;
    } else
        return NormDirection(direction - 4);
}
